#pragma once

#include <exception>
#include <sstream>
#include <string>
#include <vector>

using std::string;
using std::vector;

// класс для простого инициирования исключений
class TException : public std::exception {
private:
    string message; // error message
public:
    TException(const string& msg = "")
        : message(msg)
    {}

    virtual ~TException() throw() {}

    virtual const char * what() const throw() {
        return message.c_str();
    }
};

// Функции для разбиения строки на части. Пустые токены игнорируются. SplitString("a|b||c", '|') --> {'a', 'b', 'c'}.
// Разбить строку по последовательностям пробельных символов. SplitString("a   b c") --> {'a', 'b', 'c'}.
vector<string> SplitString(const string& s);
// Разбить строку по переданному символу.
vector<string> SplitString(const string& s, char delim);
// Разбить строку по переданной строке. SplitString("a||b||c", "||") --> {'a', 'b', 'c'}
vector<string> SplitString(const string& s, const string& delim);

// Объединить вектор строк в одну строку, используя delim как разделитель.
string JoinString(const vector<string>& vs, char delim = ' ');
string JoinString(vector<string>::const_iterator begin, vector<string>::const_iterator end, char delim = ' ');

// Удалить пробельные символы с конца строки. Изменяет переданную строку.
void RTrim(string &s);

// Преобразование из строки в передаваемый в шаблоне тип (числовой - int, size_t, double etc.)
template<typename T>
T FromString(const string& s) {
    T result;
    std::stringstream ss(s);
    ss >> result;
    if (!ss.eof()) {
        throw TException("Failed to convert string: " + s);
    }
    return result;
}

// Преобразование из передаваемого в шаблоне типа в строку.
template<typename T>
string ToString(const T& x) {
    string result;
    std::stringstream ss;
    ss << x;
    ss >> result;
    if (!ss.eof()) {
        throw TException("Failed to convert to string");
    }
    return result;
}
